package com.rayson.yututu.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rayson.yututu.exception.BusinessException;
import com.rayson.yututu.exception.ErrorCodeEnum;
import com.rayson.yututu.exception.ThrowUtils;
import com.rayson.yututu.mapper.SpaceMapper;
import com.rayson.yututu.model.entity.Space;
import com.rayson.yututu.model.entity.SpaceUser;
import com.rayson.yututu.model.entity.User;
import com.rayson.yututu.model.enums.SpaceLevelEnum;
import com.rayson.yututu.model.enums.SpaceRoleEnum;
import com.rayson.yututu.model.enums.SpaceTypeEnum;
import com.rayson.yututu.model.req.space.SpaceAddReq;
import com.rayson.yututu.model.req.space.SpaceEditReq;
import com.rayson.yututu.model.req.space.SpaceListReq;
import com.rayson.yututu.model.req.space.SpaceUpdateReq;
import com.rayson.yututu.model.vo.SpaceVO;
import com.rayson.yututu.service.SpaceService;
import com.rayson.yututu.service.SpaceUserService;
import com.rayson.yututu.service.UserService;
import com.rayson.yututu.util.PageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author wulei
 * @description 针对表【space(用户空间表)】的数据库操作Service实现
 * @createDate 2025-01-11 11:30:19
 */
@Slf4j
@Service
public class SpaceServiceImpl extends ServiceImpl<SpaceMapper, Space>
        implements SpaceService {

    private static final Map<String, Object> SPACE_MAP = new ConcurrentHashMap<>();

    @Resource
    private UserService userService;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Lazy
    @Resource
    private SpaceUserService spaceUserService;

    // @Lazy
    // @Resource
    // private DynamicShardingManager dynamicShardingManager;


    @Override
    public Page<SpaceVO> listSpacePage(SpaceListReq spaceListReq) {
        Page<SpaceVO> page = PageUtil.getPage(spaceListReq);
        return this.baseMapper.listSpacePage(page, spaceListReq);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addSpace(SpaceAddReq spaceAddReq) {
        Space space = new Space();
        BeanUtils.copyProperties(spaceAddReq, space);
        // 填充容量和大小
        fillSpace(space);
        User currentUser = userService.getCurrentUser();
        String userId = currentUser.getId();
        space.setUserId(userId);
        if (!SpaceLevelEnum.isCommon(space.getSpaceLevel()) && !userService.isAdmin(currentUser)) {
            throw new BusinessException(ErrorCodeEnum.PARAM_ERROR, "普通用户不能创建高级空间");
        }
        // 一个用户只能拥有一个私有空间 或 1个团队空间
        Object lock = SPACE_MAP.computeIfAbsent(userId, k -> new Object());
        synchronized (lock) {
            return transactionTemplate.execute(status -> {
                boolean exists = lambdaQuery()
                        .eq(Space::getUserId, userId)
                        .eq(Space::getSpaceType, spaceAddReq.getSpaceType())
                        .exists();
                ThrowUtils.throwIf(exists, ErrorCodeEnum.OPERATION_ERROR, "一个用户只能拥有一个私有空间");
                boolean result = this.save(space);
                if (result && SpaceTypeEnum.TEAM_SPACE.getValue().equals(spaceAddReq.getSpaceType())) {
                    SpaceUser spaceUser = new SpaceUser();
                    spaceUser.setSpaceId(space.getId());
                    spaceUser.setUserId(userId);
                    spaceUser.setSpaceRole(SpaceRoleEnum.ADMIN.name());
                    spaceUserService.save(spaceUser);
                }
                // 如果是团队空间且是旗舰版
                // dynamicShardingManager.createSpacePictureTable(space);
                log.info("{}创建空间,数据库执行结果: {}", userId, result);
                return space.getId();
            });
        }
    }

    @Override
    public void editSpace(SpaceEditReq spaceEditReq) {
        String spaceId = spaceEditReq.getId();
        Space space = getById(spaceId);
        ThrowUtils.throwIf(Objects.isNull(space), ErrorCodeEnum.OPERATION_ERROR, "空间不存在");
        String spaceName = spaceEditReq.getSpaceName();
        if (StrUtil.equals(space.getSpaceName(), spaceName)) {
            log.info("修改前后空间名称相同，无须更改！！");
            return;
        }
        Space update = new Space();
        update.setId(spaceId);
        update.setSpaceName(spaceName);
        boolean result = updateById(update);
        log.info("修改空间名称,数据库执行结果: {}", result);
    }

    @Override
    public void updateSpaceByAdmin(SpaceUpdateReq spaceUpdateReq) {
        String spaceId = spaceUpdateReq.getId();
        Space space = getById(spaceId);
        ThrowUtils.throwIf(Objects.isNull(space), ErrorCodeEnum.OPERATION_ERROR, "空间不存在");
        Space update = new Space();
        BeanUtils.copyProperties(spaceUpdateReq, update);
        this.fillSpace(update);
        boolean result = updateById(update);
        log.info("管理员修改空间,数据库执行结果: {}", result);
    }

    @Override
    public void checkSpace(String spaceId, User loginUser, boolean checkCapability) {
        // 空间是否存在
        Space space = getById(spaceId);
        if (Objects.isNull(space) || StrUtil.isBlank(space.getId())) {
            throw new BusinessException(ErrorCodeEnum.NOT_FOUND_ERROR, "空间不存在");
        }
        // 当前用户是否是空间所属人 或者 管理员
        if (!StrUtil.equals(space.getUserId(), loginUser.getId()) && !userService.isAdmin(loginUser)) {
            throw new BusinessException(ErrorCodeEnum.OPERATION_ERROR, "当前用户不是空间所属人");
        }
        if (checkCapability) {
            // 校验空间额度
            if (space.getTotalCount() >= space.getMaxCount()) {
                throw new BusinessException(ErrorCodeEnum.NO_AUTH, "空间条数已用完");
            }
            if (space.getTotalSize() >= space.getMaxSize()) {
                throw new BusinessException(ErrorCodeEnum.NO_AUTH, "空间容量已用完");
            }
        }
    }

    @Override
    public SpaceVO getCurrentUserSpace() {
        User currentUser = userService.getCurrentUser();
        LambdaQueryWrapper<Space> queryWrapper = lambdaQuery().getWrapper()
                .eq(Space::getSpaceType, SpaceTypeEnum.PRIVATE_SPACE.getValue())
                .eq(Space::getUserId, currentUser.getId());
        Space space = getOne(queryWrapper);
        if (Objects.isNull(space) || StrUtil.isBlank(space.getId())) {
            return null;
        }
        return Space.toVO(space);
    }

    private void fillSpace(Space space) {
        SpaceLevelEnum spaceLevelEnum = SpaceLevelEnum.getEnumByValue(space.getSpaceLevel());
        if (Objects.isNull(space.getMaxCount())) {
            space.setMaxCount(spaceLevelEnum.getMaxCount());
        }
        if (Objects.isNull(space.getMaxSize())) {
            space.setMaxSize(spaceLevelEnum.getMaxSize());
        }
    }
}




